﻿/*
 * Created by SharpDevelop.
 * User: Corrado Mio
 * Date: 04/11/2011
 * Time: 14:07
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.IO;

namespace CSharpExt.IO
{
	/// <summary>
	/// Formato del file:
	/// 
	/// - i primi 4 byte usati come header, seguiti da
	/// - 4 byte lunghezza buffer
	/// - N byte dati buffer
	/// 
	/// 
	/// 
	/// </summary>
	public class StreamToBuffers
	{
		#region Private Data
		
		private String _directory;
		private String _fileName;
		private int    _fileIndex;
		private long   _bytesAvailable;
		
		private String _filePath;
		
		private bool _closeOnEnd;
		
		private Stream _stream;
		
		#endregion
		
		#region Constructor
		
		public StreamToBuffers()
		{
		}
		
		#endregion
		
		#region Properties
		
		public String FilePath
		{
			set 
			{
				_filePath = Path.GetFullPath(value);
				_directory = Path.GetDirectoryName(_filePath);
				_fileName  = Path.GetFileName(_filePath);
			}
		}
		
		public bool CloseOnEnd
		{
			set { _closeOnEnd = value; }
		}
		
		#endregion
		
		#region Operations
		
		public void Open()
		{
			if (!File.Exists(_filePath))
				return;
			
			_bytesAvailable = new FileInfo(_filePath).Length;
			
			_stream = File.OpenRead(_filePath);

			// salta i primi 4 byte contenenti l'header			
			readInt();
		}
		
		public void Close()
		{
			if (_stream != null)
				_stream.Close();
		}
		
		public byte[] ReadBuffer()
		{
		retry:
			int count = readInt();
			byte[] buffer = readBuffer(count);
			
			if (buffer != null)
				return buffer;
			
			if (_closeOnEnd)
				return buffer;
			
			Close();
			Open();
			
			goto retry;
		}
		
		private int readInt()
		{
			if (_bytesAvailable < 4)
				return 0;
			
			int count = 0;
			count += (_stream.ReadByte() <<  0);
			count += (_stream.ReadByte() <<  8);
			count += (_stream.ReadByte() << 16);
			count += (_stream.ReadByte() << 24);
			
			_bytesAvailable -= 4;
			
			return count;
		}
		
		private byte[] readBuffer(int count)
		{
			if (_bytesAvailable == 0 || _bytesAvailable < count)
				return null;
			
			byte[] buffer = new byte[count];
			
			_stream.Read(buffer, 0, count);
			
			_bytesAvailable -= count;
			
			return buffer;
		}
		
		#endregion
		
		
	}
}
